﻿//
//  Copyright (c) 2009-2011 Liang Quan Qing.
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
//  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
//  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
//  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
//  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
//  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
//  SUCH DAMAGE.
//

#include <stddef.h>
#include <string.h>
#include <memory.h>
#include "fastconv.h"
#include "fcnv_config.h"
#include "fcnvlocal.h"

#include "tab/ascii.h"
#include "tab/cp1250.h"
#include "tab/cp1251.h"
#include "tab/cp1252.h"
#include "tab/cp1253.h"
#include "tab/cp1254.h"
#include "tab/cp1255.h"
#include "tab/cp1256.h"
#include "tab/cp1257.h"
#include "tab/cp1258.h"
#include "tab/cp874.h"
#include "tab/cp437.h"
#include "tab/cp932.h"
#include "tab/cp949.h"
#include "tab/big5.h"
#include "tab/gbk.h"
#include "tab/iso_8859_1.h"
#include "tab/iso_8859_2.h"
#include "tab/iso_8859_3.h"
#include "tab/iso_8859_4.h"
#include "tab/iso_8859_5.h"
#include "tab/iso_8859_6.h"
#include "tab/iso_8859_7.h"
#include "tab/iso_8859_8.h"
#include "tab/iso_8859_9.h"
#include "tab/iso_8859_10.h"
#include "tab/iso_8859_11.h"
#include "tab/iso_8859_13.h"
#include "tab/iso_8859_14.h"
#include "tab/iso_8859_15.h"
#include "tab/KOI8_R.h"
#include "tab/KOI8_U.h"
#include "tab/sbcs.h"
#include "tab/dbcs.h"

union _tagTestEndianOrder
{
    unsigned int dword;
    unsigned char bytes[4];
};

static unsigned int GetFcnvDescTabIndex(const char *pEncodingName);

const fcnvdesc_t fcnvDescTab[] =
{
    { NULL,         0, 0, CHARSET_TYPE_NONE     , NULL },      //0
    { "UTF-8",      1, 4, CHARSET_TYPE_UTF_8    , NULL },      //1
    { "UTF-16LE",   2, 4, CHARSET_TYPE_UTF_16LE , NULL },      //2
    { "UTF-16BE",   2, 4, CHARSET_TYPE_UTF_16BE , NULL },      //3
    { "UTF-32LE",   4, 4, CHARSET_TYPE_UTF_32LE , NULL },      //4
    { "UTF-32BE",   4, 4, CHARSET_TYPE_UTF_32BE , NULL },      //5
    { "UTF-16",     2, 4, CHARSET_TYPE_UTF_16   , NULL },      //6
    { "UTF-32",     4, 4, CHARSET_TYPE_UTF_32   , NULL },      //7
    { "UTF-7",      1, 4, CHARSET_TYPE_UTF_7    , NULL },      //8
    { "ASCII",      1, 1, CHARSET_TYPE_SBCS     , &ascii_fntab },      //9     //USA ASCII
    { "cp1250",     1, 1, CHARSET_TYPE_SBCS     , &cp1250_fntab },      //10    //Windows - Central Europe
    { "cp1251",     1, 1, CHARSET_TYPE_SBCS     , &cp1251_fntab },      //11    //Windows - Cyrillic
    { "cp1252",     1, 1, CHARSET_TYPE_SBCS     , &cp1252_fntab },      //12    //Windows - Latin I
    { "cp1253",     1, 1, CHARSET_TYPE_SBCS     , &cp1253_fntab },      //13    //Windows - Greek
    { "cp1254",     1, 1, CHARSET_TYPE_SBCS     , &cp1254_fntab },      //14    //Windows - Turkish
    { "cp1255",     1, 1, CHARSET_TYPE_SBCS     , &cp1255_fntab },      //15    //Windows - Hebrew
    { "cp1256",     1, 1, CHARSET_TYPE_SBCS     , &cp1256_fntab },      //16    //Windows - Arabic
    { "cp1257",     1, 1, CHARSET_TYPE_SBCS     , &cp1257_fntab },      //17    //Windows - Baltic
    { "cp1258",     1, 1, CHARSET_TYPE_SBCS     , &cp1258_fntab },      //18    //Windows - Vietnam
    { "cp874",      1, 1, CHARSET_TYPE_SBCS     , &cp874_fntab  },      //19    //Windows - Thai
    { "Shift-JIS",  1, 2, CHARSET_TYPE_MBCS     , &cp932_fntab  },      //20    //Japanese Shift-JIS
    { "cp949",      1, 2, CHARSET_TYPE_MBCS     , &cp949_fntab  },      //21    //Korean
    { "GBK",        1, 2, CHARSET_TYPE_MBCS     , &gbk_fntab    },      //22    //Simplified Chinese
    { "GB18030",    1, 4, CHARSET_TYPE_MBCS     , NULL },      //23    //Simplified Chinese (New Standard)
    { "BIG5",       1, 2, CHARSET_TYPE_MBCS     , &big5_fntab   },      //24    //Traditional Chinese
    { NULL,         0, 0, CHARSET_TYPE_MBCS     , NULL },      //25    //for BIG5-HKSCS (in future)
    { NULL,         0, 0, CHARSET_TYPE_MBCS     , NULL },      //26    //for BIG5-2003  (in future)
    { "ISO-8859-1", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_1_fntab},  //27     //ISO-8859-1  -  Latin 1
    { "ISO-8859-2", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_2_fntab},  //28     //ISO-8859-2  -  Latin 2
    { "ISO-8859-3", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_3_fntab},  //29     //ISO-8859-3  -  Latin 3
    { "ISO-8859-4", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_4_fntab},  //30     //ISO-8859-4  -  Baltic
    { "ISO-8859-5", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_5_fntab},  //31     //ISO-8859-5  -  Cyrillic
    { "ISO-8859-6", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_6_fntab},  //32     //ISO-8859-6  -  Arabic
    { "ISO-8859-7", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_7_fntab},  //33     //ISO-8859-7  -  Greek
    { "ISO-8859-8", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_8_fntab},  //34     //ISO-8859-8  -  Hebrew
    { "ISO-8859-9", 1, 1, CHARSET_TYPE_SBCS     , &iso_8859_9_fntab},  //35     //ISO-8859-9  -  Turkish
    { "ISO-8859-10",1, 1, CHARSET_TYPE_SBCS     , &iso_8859_10_fntab}, //36     //ISO-8859-10 -  Nordic
    { "ISO-8859-11",1, 1, CHARSET_TYPE_SBCS     , &iso_8859_11_fntab}, //37     //ISO-8859-11 -  Thai
    { "ISO-8859-13",1, 1, CHARSET_TYPE_SBCS     , &iso_8859_13_fntab}, //38     //ISO-8859-13 -  Baltic Rim
    { "ISO-8859-14",1, 1, CHARSET_TYPE_SBCS     , &iso_8859_14_fntab}, //39     //ISO-8859-14 -  Celtic
    { "ISO-8859-15",1, 1, CHARSET_TYPE_SBCS     , &iso_8859_15_fntab}, //40     //ISO-8859-15 -  Latin 9
    { "cp437"      ,1, 1, CHARSET_TYPE_SBCS     , &cp437_fntab},       //41     //DOS OEM 437 -  United States
    { "KOI8-R"     ,1, 1, CHARSET_TYPE_SBCS     , &KOI8_R_fntab},      //42     //KOI8-R
    { "KOI8-U"     ,1, 1, CHARSET_TYPE_SBCS     , &KOI8_U_fntab},      //43     //KOI8-U
};


//  initialize a fcnv_t variable to default state
int fcnv_Init(const char* pEncodingName, fcnv_t* pfcnv)
{
    priv_t * pd;
    unsigned int    id;

    pfcnv->inCount = 0;
    pfcnv->outCount = 0;
    pfcnv->reserved = 0;
    pd = (priv_t*) pfcnv->privdata;

    id = GetFcnvDescTabIndex(pEncodingName);
    if ( ! id )
    {
        pfcnv->error = FCNV_ERR_NOT_SUPPORTED;
        return -1;
    }
    pd->csid = id;
    pd->boUseDefaultChar = 1;
    memset(pd->pDefaultChar, 0, sizeof(pd->pDefaultChar));
    pd->pDefaultChar[0] = '?';
    pd->DefaultWChar = 0x003F;
    pd->charsize = 1;
    pd->defaultUTF8Len = 1;
    memset(pd->pDefalutUTF8, 0, sizeof(pd->pDefalutUTF8));
    pd->pDefalutUTF8[0] = '?';
    pfcnv->error = FCNV_ERR_NONE;
    if ( fcnvDescTab[pd->csid].functions )
        fcnvDescTab[pd->csid].functions->init(pfcnv);
    return sizeof(fcnv_t);
}

int fcnv_InitW(const WChar_t* pEncodingName, fcnv_t* pfcnv)
{
    unsigned char tmpBuf[64];
    unsigned i = 0;

    tmpBuf[63] = '\0';
    while ( i < 63 )
    {
        if ( pEncodingName[i] >= 0x80 )
        {
            pfcnv->error = FCNV_ERR_NOT_SUPPORTED;
            return 0;
        }
        tmpBuf[i] = (unsigned char) (pEncodingName[i]);
        if ( ! pEncodingName[i] )
            break;
        i++;
    }
    return fcnv_Init(tmpBuf, pfcnv);
}

int fcnv_InitD(const DChar_t* pEncodingName, fcnv_t* pfcnv)
{
    unsigned char tmpBuf[64];
    unsigned i = 0;

    tmpBuf[63] = '\0';
    while ( i < 63 )
    {
        if ( pEncodingName[i] >= 0x80 )
        {
            pfcnv->error = FCNV_ERR_NOT_SUPPORTED;
            return 0;
        }
        tmpBuf[i] = pEncodingName[i];
        if ( ! pEncodingName[i] )
            break;
        i++;
    }
    return fcnv_Init(tmpBuf, pfcnv);
}

int fcnv_Setup( fcnv_t*     pfcnv,
                int         boUseDefaultChar,
                const char* pDefaultChar,
                WChar_t     DefaultWChar)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    pd->boUseDefaultChar = boUseDefaultChar;
    if ( DefaultWChar != 0x0000 )
        pd->DefaultWChar = DefaultWChar;
    if ( pDefaultChar != NULL && pDefaultChar[0] != 0 )
    {
        memset(pd->pDefaultChar, 0, 8);
        memcpy(pd->pDefaultChar, pDefaultChar, fcnv_GetMaxCharSize(pfcnv) );
    }
    pfcnv->error = FCNV_ERR_NONE;
    return sizeof(fcnv_t);
}

int fcnv_GetMaxCharSize(const fcnv_t* pfcnv)
{
    priv_t * pd;
    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].maxCharSize;
}

int fcnv_GetMinCharSize(const fcnv_t* pfcnv)
{
    priv_t * pd;
    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].minCharSize;
}

int fcnv_ToUTF16(   fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    WChar_t *   pBuffer,
                    size_t      destSizeInWChars)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->t16(pfcnv,srcString,srcSizeInBytes,pBuffer,destSizeInWChars);
}

int fcnv_FromUTF16( fcnv_t*     pfcnv,
                    const WChar_t* srcString,
                    size_t      srcSizeInWChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->f16(pfcnv,srcString,srcSizeInWChars,pBuffer,destSizeInBytes);
}

int fcnv_ToUnicode( fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    WChar_t *   pBuffer,
                    size_t      destSizeInWChars)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->t16(pfcnv,srcString,srcSizeInBytes,pBuffer,destSizeInWChars);
}

int fcnv_FromUnicode( fcnv_t*     pfcnv,
                    const WChar_t* srcString,
                    size_t      srcSizeInWChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->f16(pfcnv,srcString,srcSizeInWChars,pBuffer,destSizeInBytes);
}

int fcnv_ToUTF8(    fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    char *      pBuffer,
                    size_t      destSizeInBytes)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->t8(pfcnv,srcString,srcSizeInBytes,pBuffer,destSizeInBytes);
}

int fcnv_FromUTF8(  fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    char *      pBuffer,
                    size_t      destSizeInBytes)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->f8(pfcnv,srcString,srcSizeInBytes,pBuffer,destSizeInBytes);
}

int fcnv_ToUTF32(   fcnv_t*     pfcnv,
                    const char* srcString,
                    size_t      srcSizeInBytes,
                    DChar_t *   pBuffer,
                    size_t      destSizeInDChars)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->t32(pfcnv,srcString,srcSizeInBytes,pBuffer,destSizeInDChars);
}

int fcnv_FromUTF32( fcnv_t*     pfcnv,
                    const DChar_t*srcString,
                    size_t      srcSizeInDChars,
                    char *      pBuffer,
                    size_t      destSizeInBytes)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->f32(pfcnv,srcString,srcSizeInDChars,pBuffer,destSizeInBytes);
}

int fcnv_UTF16SwapEndian(WChar_t * pBuffer, size_t sizeInWChars)
{
    size_t len, i;
    WChar_t wch;

    len = sizeInWChars ? sizeInWChars : wstrlen(pBuffer);
    for ( i = 0; i < len; i++ )
    {
        wch = pBuffer[i];
        pBuffer[i] = ((wch&0xff)<<8) | ((wch>>8)&0xff);
    }
    return (int)len;
}

int fcnv_UTF32SwapEndian(DChar_t * pBuffer, size_t sizeInDChars)
{
    size_t len, i;
    DChar_t dch;

    len = sizeInDChars ? sizeInDChars : dstrlen(pBuffer);
    for ( i = 0; i < len; i++ )
    {
        dch = pBuffer[i];
        pBuffer[i] = ((dch&0xff)<<24) | (((dch>>8)&0xff)<<16) | (((dch>>16)&0xff)<<8) | ((dch>>24)&0xff);
    }
    return (int)len;
}

int fcnv_UnicodeSwapEndian(WChar_t * pBuffer, size_t sizeInWChars)
{
    return fcnv_UTF16SwapEndian(pBuffer,sizeInWChars);
}

int fcnv_GetFirstCharLength(const fcnv_t* pfcnv, const char* s)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->FirstCharLength(s);
}

int fcnv_IsLeadByte(const fcnv_t* pfcnv, const char* s)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->IsLeadByte(s);
}

fpGetFirstCharLen_t fcnv_GetFp_GetFirstCharLength(const fcnv_t* pfcnv)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->FirstCharLength;
}

fpIsLeadByte_t fcnv_GetFp_IsLeadByte(const fcnv_t* pfcnv)
{
    priv_t * pd;

    pd = (priv_t*) pfcnv->privdata;
    return fcnvDescTab[pd->csid].functions->IsLeadByte;
}

int fcnv_CheckUTF8String(const char* string, size_t size)
{
    size_t n;
    unsigned char ch1, ch2, ch3, ch4, ch5, ch6;
    const unsigned char * buffer;

    if (string == NULL)
        return 0;
    if (size == 0)
        size = strlen(string) + 1;

    buffer = (const unsigned char *) string;
    n = 0;
    
    while ( n < size )
    {
        ch1 = buffer[n+0];
        if ( ch1 < 0x80 )
            n++;
        else if ( (ch1 & 0xE0) == 0xC0 )
        {
            if (n+1 >= size)
                return 0;
            ch2 = buffer[n+1];
            if ( (ch2 & 0xC0) != 0x80 )
                return 0;
            n += 2;
        }
        else if ( (ch1 & 0xF0) == 0xE0 )
        {
            if (n+2 >= size)
                return 0;
            ch2 = buffer[n+1];
            ch3 = buffer[n+2];
            if ( (ch2 & 0xC0) != 0x80 )
                return 0;
            if ( (ch3 & 0xC0) != 0x80 )
                return 0;
            n += 3;
        }
        else if ( (ch1 & 0xF8) == 0xF0 )
        {
            if (n+3 >= size)
                return 0;
            ch2 = buffer[n+1];
            ch3 = buffer[n+2];
            ch4 = buffer[n+3];
            if ( (ch2 & 0xC0) != 0x80 )
                return 0;
            if ( (ch3 & 0xC0) != 0x80 )
                return 0;
            if ( (ch4 & 0xC0) != 0x80 )
                return 0;
            n += 4;
        }
        else if ( (ch1 & 0xFC) == 0xF8 )
        {
            if (n+4 >= size)
                return 0;
            ch2 = buffer[n+1];
            ch3 = buffer[n+2];
            ch4 = buffer[n+3];
            ch5 = buffer[n+4];
            if ( (ch2 & 0xC0) != 0x80 )
                return 0;
            if ( (ch3 & 0xC0) != 0x80 )
                return 0;
            if ( (ch4 & 0xC0) != 0x80 )
                return 0;
            if ( (ch5 & 0xC0) != 0x80 )
                return 0;
            n += 5;
        }
        else if ( (ch1 & 0xFE) == 0xFC )
        {
            if (n+5 >= size)
                return 0;
            ch2 = buffer[n+1];
            ch3 = buffer[n+2];
            ch4 = buffer[n+3];
            ch5 = buffer[n+4];
            ch6 = buffer[n+5];
            if ( (ch2 & 0xC0) != 0x80 )
                return 0;
            if ( (ch3 & 0xC0) != 0x80 )
                return 0;
            if ( (ch4 & 0xC0) != 0x80 )
                return 0;
            if ( (ch5 & 0xC0) != 0x80 )
                return 0;
            if ( (ch6 & 0xC0) != 0x80 )
                return 0;
            n += 6;
        }
        else
            return 0;
    }
    return 1;
}

int fcnv_IsBigEndian(void)
{
    union _tagTestEndianOrder num;
    num.dword = 0x12345678;
    if ( num.bytes[0] == 0x12 )
        return 1;
    else
        return 0;
}

int fcnv_IsLittleEndian(void)
{
    union _tagTestEndianOrder num;
    num.dword = 0x12345678;
    if ( num.bytes[0] == 0x78 )
        return 1;
    else
        return 0;
}

const char* fcnv_GetSystemDefaultCharset(void)
{
    return "GBK";
}

static unsigned int GetFcnvDescTabIndex(const char *pEncodingName)
{
    const static struct _supportName fcnvSupportNameList[] =
    {
        { "UTF-8"       , 1 },
        { "UTF-16LE"    , 2 },
        { "UTF-16BE"    , 3 },
        { "UTF-32LE"    , 4 },
        { "UTF-32BE"    , 5 },
        { "UTF-16"      , 6 },
        { "UTF-32"      , 7 },
        //UTF-8
        { "cp65001"     , 1 },
        { "65001"       , 1 },
        { "UTF8"        , 1 },
        { "windows-65001",1 },
        //UTF-16
        { "UTF16"       , 6 },
        { "Unicode"     , 6 },
        { "UCS-2"       , 6 },
        { "UCS2"        , 6 },
        //UTF-16LE
        { "UTF16LE"     , 2 },
        { "UCS-2LE"     , 2 },
        { "UCS2LE"      , 2 },
        { "1200"        , 2 },
        { "cp1200"      , 2 },
        { "windows-1200", 2 },
        //UTF-16BE
        { "UTF16BE"     , 3 },
        { "UCS-2BE"     , 3 },
        { "UCS2BE"      , 3 },
        { "1201"        , 3 },
        { "cp1201"      , 3 },
        { "windows-1201", 3 },
        //UTF-32
        { "UTF32"       , 7 },
        { "UCS-4"       , 7 },
        { "UCS4"        , 7 },
        //UTF-32LE
        { "UTF32LE"     , 4 },
        { "UCS-4LE"     , 4 },
        { "UCS4LE"      , 4 },
        { "12000"       , 4 },
        { "cp12000"     , 4 },
        { "windows-12000",4 },
        //UTF-32BE
        { "UTF32BE"     , 5 },
        { "UCS-4BE"     , 5 },
        { "UCS4BE"      , 5 },
        { "12001"       , 5 },
        { "cp12001"     , 5 },
        { "windows-12001",5 },
        //UTF-7
        { "UTF-7"       , 8 },
        { "UTF7"        , 8 },
        { "65000"       , 8 },
        { "cp65000"     , 8 },
        { "windows-65000",8 },
        //ASCII
        { "ASCII"       , 9 },
        { "US-ASCII"    , 9 },
        //cp1252
        { "cp1252"      , 12},
        { "1252"        , 12},
        { "windows-1252", 12},
        //GBK
        { "GBK"         , 22},
        { "GB2312"      , 22},
        { "GB2312-80"   , 22},
        { "GB2312-1980" , 22},
        { "GB-2312"     , 22},
        { "cp936"       , 22},
        { "936"         , 22},
        { "windows-936" , 22},
        { "EUC-CN"      , 22},
        { "EUCCN"       , 22},
        //GB18030
        { "GB18030"     , 23},
        { "GB-18030"    , 23},
        { "GB18030-2000", 23},
        { "54936"       , 23},
        { "cp54936"     , 23},
        { "windows-54936",23},
        //Big-5
        { "BIG5"        , 24},
        { "BIG-5"       , 24},
        { "BIG-FIVE"    , 24},
        { "BIGFIVE"     , 24},
        { "cp950"       , 24},
        { "950"         , 24},
        { "windows-950" , 24},
        { "EUC-TW"      , 24},
        { "EUCTW"       , 24},
        //BIG5-HKSCS

        //BIG5-2003

        //cp1250
        { "cp1250"      , 10},
        { "1250"        , 10},
        { "windows-1250", 10},
        //cp1251
        { "cp1251"      , 11},
        { "1251"        , 11},
        { "windows-1251", 11},
        //cp1253
        { "cp1253"      , 13},
        { "1253"        , 13},
        { "windows-1253", 13},
        //cp1254
        { "cp1254"      , 14},
        { "1254"        , 14},
        { "windows-1254", 14},
        //cp1255
        { "cp1255"      , 15},
        { "1255"        , 15},
        { "windows-1255", 15},
        //cp1256
        { "cp1256"      , 16},
        { "1256"        , 16},
        { "windows-1256", 16},
        //cp1257
        { "cp1257"      , 17},
        { "1257"        , 17},
        { "windows-1257", 17},
        //cp1258
        { "cp1258"      , 18},
        { "1258"        , 18},
        { "windows-1258", 18},
        //cp874
        { "cp874"       , 19},
        { "874"         , 19},
        { "windows-874" , 19},
        { "TIS-620"     , 19},
        //Shift-JIS
        { "Shift-JIS"   , 20},
        { "SHIFT_JIS"   , 20},
        { "SHIFTJIS"    , 20},
        { "SJIS"        , 20},
        { "MS_KANJI"    , 20},
        { "cp932"       , 20},
        { "932"         , 20},
        { "windows-932" , 20},
        //Korean
        { "cp949"       , 21},
        { "949"         , 21},
        { "windows-949" , 21},
        { "UHC"         , 21},
        { "Korean"      , 21},
        { "ksc"         , 21},
        { "KSC_5601"    , 21},
        { "KS_C_5601-1987", 21},
        { "KS_C_5601-1989", 21},
        { "CSKSC56011987", 21},
        { "EUC-KR"      , 21},
        { "EUCKR"       , 21},
        { "CSEUCKR"     , 21},
        //ISO-8859-1
        { "ISO-8859-1"  , 27},
        { "ISO8859-1"   , 27},
        { "ISO_8859-1"  , 27},
        { "ISO_8859_1"  , 27},
        { "LATIN1"      , 27},
        { "8859_1"      , 27},
        { "ISO_8859-1:1987", 27},
        //ISO-8859-2
        { "ISO-8859-2"  , 28},
        //ISO-8859-3
        { "ISO-8859-3"  , 29},
        //ISO-8859-4
        { "ISO-8859-4"  , 30},
        //ISO-8859-5
        { "ISO-8859-5"  , 31},
        //ISO-8859-6
        { "ISO-8859-6"  , 32},
        //ISO-8859-7
        { "ISO-8859-7"  , 33},
        //ISO-8859-8
        { "ISO-8859-8"  , 34},
        //ISO-8859-9
        { "ISO-8859-9"  , 35},
        //ISO-8859-10
        { "ISO-8859-10" , 36},
        //ISO-8859-11
        { "ISO-8859-11" , 37},
        //ISO-8859-13
        { "ISO-8859-13" , 38},
        //ISO-8859-14
        { "ISO-8859-14" , 39},
        //ISO-8859-15
        { "ISO-8859-15" , 40},
        //DOS OEM cp737
        {"cp437"        , 41},
        //
        {"KOI8-R"       , 42},
        //
        {"KOI8-U"       , 43},

        { NULL          , 0 }
    };
    unsigned int i;
    if ( *pEncodingName == '\0' || pEncodingName == NULL )
        return 0;
    i = 0;
    while (1)
    {
        if ( fcnvSupportNameList[i].encodingName == NULL)
            return 0;
        if ( ! stricmp( fcnvSupportNameList[i].encodingName, pEncodingName) )
            return fcnvSupportNameList[i].index;
        i++;
    }
    return 0;
}



